package vn.huync.smsbackupandrestore;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import vn.huync.smsbackupandrestore.others.Utils;
import vn.huync.smsbackupandrestore.others.Utils.SyncListener;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.dropbox.client2.DropboxAPI;
import com.dropbox.client2.android.AndroidAuthSession;
import com.dropbox.client2.exception.DropboxException;
import com.dropbox.client2.session.AccessTokenPair;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.drive.Drive;
import com.google.api.services.drive.Drive.Files;
import com.google.api.services.drive.model.FileList;
import com.google.api.services.drive.model.ParentReference;
import com.nch.smsbackupandrestore.R;

public class LogInSyncServiceActivity extends Activity implements SyncListener {
	static final int REQUEST_ACCOUNT_PICKER = 1;
	static final int REQUEST_AUTHORIZATION = 2; 
	static final String SAVED_FOLDER_NAME_DRIVE = "SmsBackup";
	
	static final String DRIVE_ACCOUNT_KEY = "driveAccountKey";
	MyApp myApp;
	
	DropboxAPI<AndroidAuthSession> mDBApi;
	int[] outArray = null;
	
	// Dropbox
	Button loginDropboxButton, syncNowButton;
	TextView userIdDropboxTextView;
	
	Button loginDriveButton;
	TextView userIdDriveTextView;
	TextView saveLocationTextView;
	Button copyToRootFolderButton;
	
	Thread syncThread;
	Thread tSetText;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.login);
		setTitle(R.string.dropbox);
		
		myApp = (MyApp)getApplicationContext();
		mDBApi = myApp.mDBApi;
		loginDropboxButton = (Button)findViewById(R.id.b_login);
		loginDropboxButton.setOnClickListener(onClickListener);
		syncNowButton = (Button)findViewById(R.id.b_sync_now);
		syncNowButton.setOnClickListener(onClickListener);
		userIdDropboxTextView = (TextView)findViewById(R.id.t_user_id);
		copyToRootFolderButton = (Button)findViewById(R.id.copyToRootFolderButton);
		
		loginDriveButton = (Button)findViewById(R.id.b_login_drive);
		userIdDriveTextView = (TextView)findViewById(R.id.t_user_id_drive);
		loginDriveButton.setOnClickListener(onClickListener);
		copyToRootFolderButton.setOnClickListener(onClickListener);
		
		//check loged in or not
		SetIsLoginDropbox(myApp.isLogedInDropbox);
		Log.i("", "Is login : " + myApp.isLogedInDropbox);

//		if(myApp.isLogedInDropbox == true)
//		{
//			// get access dropbox permission
//			AccessTokenPair accessTokenPair = GetAccessTokenPair();
//			mDBApi.getSession().setAccessTokenPair(accessTokenPair);
//		}
		
		Utils.autoLoginDrive(myApp, getApplicationContext());
		updateUiDrive();
		updateUISyncButton();
		
		//check internet connection
        if(Utils.isInternetConnected(this) == false){
        	Utils.ShowToast(this, R.string.should_turn_on_internet);
        }
	}
	
	void SetIsLoginDropbox(boolean isLogin){
		myApp.isLogedInDropbox = isLogin;
		if(isLogin == true){
			loginDropboxButton.setText(R.string.logout);
			
			tSetText = new Thread(new Runnable() {
				
				public void run() {
					try {
						
						final String displayName = mDBApi.accountInfo().displayName;
					
						runOnUiThread(new Runnable() {
							
							public void run() {
								userIdDropboxTextView.setText(displayName);
								
							}
						});
						
					} catch (DropboxException e) {
						e.printStackTrace();
					}
				}
			});
			tSetText.start();
		}
		else{
			loginDropboxButton.setText(R.string.login);
			userIdDropboxTextView.setText("");
		}
	}
	
	View.OnClickListener onClickListener = new View.OnClickListener() {
		
		@SuppressWarnings("deprecation")
		public void onClick(View v) {
			if(v.getId() == R.id.b_login)
			{
				if(myApp.isLogedInDropbox == false)
					mDBApi.getSession().startAuthentication(LogInSyncServiceActivity.this);
				else 
				{
					AlertDialog.Builder builder = new AlertDialog.Builder(LogInSyncServiceActivity.this);
			    	builder
			    	.setTitle(R.string.warning)
			    	.setMessage(R.string.logout_warning_message)
			    	.setIcon(android.R.drawable.ic_dialog_alert)
			    	.setNegativeButton(android.R.string.yes, new DialogInterface.OnClickListener() {
			    	    public void onClick(DialogInterface dialog, int which) {			      	
			    	    	ReplaceKey();
							mDBApi.getSession().unlink();
							SetIsLoginDropbox(false);
							updateUISyncButton();
			    	    }
			    	})
			    	.setPositiveButton(android.R.string.no, null)						//Do nothing on no
			    	.show();
				}
			}
			else if(v.getId() == R.id.b_login_drive){
				if(Utils.getDriveUsername(getApplicationContext()) != null){		// logout
					AlertDialog.Builder builder = new AlertDialog.Builder(LogInSyncServiceActivity.this);
			    	builder
			    	.setTitle(R.string.warning)
			    	.setMessage(R.string.logout_warning_message)
			    	.setIcon(android.R.drawable.ic_dialog_alert)
			    	.setNegativeButton(android.R.string.yes, new DialogInterface.OnClickListener() {
			    	    public void onClick(DialogInterface dialog, int which) {			      	
			    	    	Utils.logoutDrive(getApplicationContext());
							updateUiDrive();
							updateUISyncButton();
							copyToRootFolderButton.setEnabled(false);
			    	    }
			    	})
			    	.setPositiveButton(android.R.string.no, null)						//Do nothing on no
			    	.show();
				}
				else{
					startActivityForResult(myApp.credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
				}
			}
			else if(v.getId() == R.id.copyToRootFolderButton){
				copyFilesToRootFolder();
			}
			else if(v.getId() == R.id.b_sync_now){
				syncAllUseThread();
			}
		}
	};
	
	void copyFilesToRootFolder(){
		updateCopyButtonWhenCopying(true);
		Thread copyThread = new Thread(new Runnable() {
			
			public void run() {
				//get list file in drive
				List<com.google.api.services.drive.model.File> listDriveFiles = new ArrayList<com.google.api.services.drive.model.File>();
				try {
					Files.List request;
					request = myApp.service.files().list();
					request.setQ("'appdata' in parents");

					  do {
					    try {
					      FileList driveFiles = request.execute();
					      listDriveFiles.addAll(driveFiles.getItems());
					      request.setPageToken(driveFiles.getNextPageToken());
					    } catch (IOException e) {
					      System.out.println("An error occurred - copyFilesToRootFolder - list: " + e);
					      request.setPageToken(null);
					      finishCopyToRootFolder();
					    }
					  } while (request.getPageToken() != null && request.getPageToken().length() > 0);
				} catch (IOException e1) {
					e1.printStackTrace();
					finishCopyToRootFolder();
				}
				
				String saveFolderId = null;
				try {
					Files.List files = myApp.service.files().list()
							.setQ("'root' in parents and mimeType='application/vnd.google-apps.folder' and trashed=false and title = '" + SAVED_FOLDER_NAME_DRIVE + "'");
					FileList fileList = files.execute();
					List<com.google.api.services.drive.model.File> filesReceive = fileList.getItems();
					if(filesReceive.size() > 0){
						saveFolderId = filesReceive.get(0).getId();
					}
					else{
						com.google.api.services.drive.model.File body = new com.google.api.services.drive.model.File();
						body.setTitle(SAVED_FOLDER_NAME_DRIVE);
						body.setMimeType("application/vnd.google-apps.folder");
						com.google.api.services.drive.model.File file = myApp.service.files().insert(body).execute();
						saveFolderId = file.getId();
					}
				} catch (IOException e1) {
					e1.printStackTrace();
					finishCopyToRootFolder();
				}
				
				// copy
				Log.i("","Prepare copy, listDriveFIles.count " + listDriveFiles.size() );
				
				for(com.google.api.services.drive.model.File driveFile : listDriveFiles){
					com.google.api.services.drive.model.File copiedFile = new com.google.api.services.drive.model.File();
				    copiedFile.setTitle(driveFile.getTitle());
				    List<ParentReference> parents = new ArrayList<ParentReference>();
				    ParentReference parent = new ParentReference();
				    parent.setId(saveFolderId);
				    parents.add(parent);
				    
				    copiedFile.setParents(parents);
				    try {
				      myApp.service.files().copy(driveFile.getId(), copiedFile).execute();
				      Log.i("", "Copy file : " + driveFile.getTitle());
				    } catch (IOException e) {
				      System.out.println("An error occurred - copyFilesToRootFolder - copy: " + e);
				      finishCopyToRootFolder();
				    }
				}
				Log.i("","Copy done.");
				finishCopyToRootFolder();
				runOnUiThread(new Runnable() {
					public void run() {
						Toast.makeText(getApplicationContext(), getString(R.string.copy_sucessfully), Toast.LENGTH_SHORT).show();
					}
				});
			}
		});
		copyThread.start();
		
	}
	
	void finishCopyToRootFolder(){
		runOnUiThread(new Runnable() {
			
			public void run() {
				updateCopyButtonWhenCopying(false);
			}
		});
	}
	
	protected void onActivityResult(int requestCode, int resultCode, android.content.Intent data) {
		switch (requestCode) {
			case REQUEST_ACCOUNT_PICKER:
				if (resultCode == RESULT_OK && data != null && data.getExtras() != null) {
				    String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
				    if (accountName != null) {
				    	myApp.credential.setSelectedAccountName(accountName);
				    	myApp.service = new Drive.Builder(AndroidHttp.newCompatibleTransport(), new GsonFactory(), myApp.credential).build();
				    	userIdDriveTextView.setText(accountName);
				    	SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
				    	Editor editor = preferences.edit();
				    	editor.putString(DRIVE_ACCOUNT_KEY, accountName);
				    	editor.commit();
				    	updateUiDrive();
				    	
				    	// call a request to catch UserRecoverableAuthIOException
				    	Thread checkAuThread = new Thread(new Runnable() {
							
							public void run() {
								try {
									Files.List request;
									request = myApp.service.files().list();
									request.setQ("'root' in parents");
								    try {
								      request.execute();
								      syncAllUseThread();
								    } catch (UserRecoverableAuthIOException e) {
								    	// that is what we want
								    	Log.i("", "Get auth");
								    	startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
								    }
									 
								} catch (IOException e1) {
									e1.printStackTrace();
								}
							}
						});
				    	checkAuThread.start();
				    }
				}
				break;
			case REQUEST_AUTHORIZATION:
				if (resultCode == Activity.RESULT_OK) {
					syncAllUseThread();
					
				} else {
					startActivityForResult(myApp.credential.newChooseAccountIntent(), REQUEST_ACCOUNT_PICKER);
				}
				break;

		}
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		if (mDBApi.getSession().authenticationSuccessful()) {
	        try {
	            mDBApi.getSession().finishAuthentication();

	            AccessTokenPair tokens = mDBApi.getSession().getAccessTokenPair();
	            storeKeys(tokens.key, tokens.secret);
	            SetIsLoginDropbox(true);
	            syncAllUseThread();
	        } catch (IllegalStateException e) {
	            Log.i("DbAuthLog", "Error authenticating", e);
	        }
	    }
	}
	
	void syncAllUseThread(){
		runOnUiThread(new Runnable() {
			
			public void run() {
				updateSyncNowButtonWhenSyncing(true);
			}
		});
		
		Thread syncAllThread = new Thread(new Runnable() {
			
			public void run() {
				Utils.syncAll(myApp, getApplicationContext(), LogInSyncServiceActivity.this);
			}
		});
		syncAllThread.start();
	}
	
	void updateUISyncButton(){
		if(Utils.getDriveUsername(this) == null && myApp.isLogedInDropbox == false){
			syncNowButton.setEnabled(false);
		}
		else syncNowButton.setEnabled(true);
	}
	
	void storeKeys(String key, String secret)
	{
		SharedPreferences pref = this.getSharedPreferences("smsbackup", Activity.MODE_PRIVATE);
		SharedPreferences.Editor editor = pref.edit();
		editor.putString("key", key);
		editor.putString("secret", secret);
		editor.commit();
	}
	
	void ReplaceKey()
	{
		SharedPreferences pref = this.getSharedPreferences("smsbackup", Activity.MODE_PRIVATE);
		SharedPreferences.Editor editor = pref.edit();
		editor.putString("key", "");
		editor.putString("secret", "");
		editor.commit();
	}
	
	AccessTokenPair GetAccessTokenPair()
	{
		SharedPreferences pref = this.getSharedPreferences("smsbackup", Activity.MODE_PRIVATE);
		String keyDropbox = pref.getString("key", "");
		String secretDropbox = pref.getString("secret", "");
		if(keyDropbox.equals("") != true && secretDropbox.equals("")!= true)
			return new AccessTokenPair(keyDropbox, secretDropbox);
		else return null;
	}
	
	@Override
	protected void onPause() {
		if(syncThread != null)
			syncThread.interrupt();
		if(tSetText != null)
			tSetText.interrupt();
		super.onPause();
	}
	
	void updateUiDrive(){
		String driveUsername = Utils.getDriveUsername(this);
		if(driveUsername != null){
			userIdDriveTextView.setText(driveUsername);
			loginDriveButton.setText(R.string.logout);
			updateCopyButtonWhenCopying(false);
		}
		else{
			userIdDriveTextView.setText("");
			loginDriveButton.setText(R.string.login);
		}
	}
	
	void updateCopyButtonWhenCopying(boolean isCopying){
		if(isCopying){
			copyToRootFolderButton.setEnabled(false);
			copyToRootFolderButton.setText(R.string.copying);
		}
		else{
			copyToRootFolderButton.setEnabled(true);
			copyToRootFolderButton.setText(R.string.copy_to_root_folder);
		}
	}
	
	void updateSyncNowButtonWhenSyncing(boolean isSyncing){
		if(isSyncing){
			syncNowButton.setEnabled(false);
			syncNowButton.setText(R.string.synchronizing);
		}
		else{
			syncNowButton.setEnabled(true);
			syncNowButton.setText(R.string.sync_now);
		}
	}

	public void onSyncDone() {
		runOnUiThread(new Runnable() {
			
			public void run() {
				updateSyncNowButtonWhenSyncing(false);
			}
		});
	}

	public void onUserRecoverableAuthIOException(
			UserRecoverableAuthIOException e) {
		startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
	}

	public void onSyncDropboxDone(final int upload, final int download) {
		
		runOnUiThread(new Runnable() {
			
			public void run() {
				Utils.ShowToast(getApplicationContext(), getString(R.string.sync_success)
						+ ", " + upload + " " + getString(R.string.uploaded)
						+ ", " + download + " " + getString(R.string.downloaded)
						+ " " + getString(R.string.from_dropbox));
			}
		});
		
		
	}

	public void onSyncDriveDone(final int upload, final int download) {
		runOnUiThread(new Runnable() {
			
		public void run() {
			Utils.ShowToast(getApplicationContext(), getString(R.string.sync_success)
					+ ", " + upload + " " + getString(R.string.uploaded)
					+ ", " + download + " " + getString(R.string.downloaded)
					+ " " + getString(R.string.from_google_drive));
			}
		});
	}
}
